package com.nineclock.approve.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.nineclock.approve.dto.ApproveDefinitionDto;
import com.nineclock.approve.handler.ProcessNodeResolver;
import com.nineclock.approve.pojo.ApproveDefinition;
import com.nineclock.approve.service.ActivitiService;
import com.nineclock.approve.utils.ActivitiUtils;
import com.nineclock.common.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
@Slf4j
public class ActivitiServiceImpl implements ActivitiService {

    @Autowired
    private RepositoryService repositoryService;

    @Override
    public void deployProcessToActiviti(ApproveDefinition approveDefinition) {

        BpmnModel bpmnModel = new BpmnModel();

        // 创建process
        Process process = new Process();
        process.setId(ActivitiUtils.PROCESS_PREFIX + approveDefinition.getId());
        process.setName(approveDefinition.getName());

        // 获取流程数据
        String flowJson = approveDefinition.getFlowJson();
        JSONArray jsonArray = JSON.parseArray(flowJson);

        addNodeToProcess(process, jsonArray);

        // 设置proces到bpmnModel
        bpmnModel.addProcess(process);

        // 自动布局
        new BpmnAutoLayout(bpmnModel).execute();

        // 将bpmnModel转为一个xml，打印出来
        BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
        byte[] bytes = bpmnXMLConverter.convertToXML(bpmnModel);
        log.info("动态构建BPMN模型，XML信息为" + new String(bytes));

        // 部署流程
        repositoryService.createDeployment().addBpmnModel(approveDefinition.getName() + ".bpmn", bpmnModel)
                .name(approveDefinition.getName()).deploy();

    }



    @Autowired
    private List<ProcessNodeResolver> resolverList;

    /**
     * 根据流程数据，动态创建节点对象，并加入到process
     * @param jsonArray
     * @param process
     */
    private void addNodeToProcess(Process process, JSONArray jsonArray) {

        for (int i = 0; i < jsonArray.size(); i++) {

            // 获取一个个节点
            JSONObject curNode = (JSONObject) jsonArray.get(i);

            JSONObject nextNode = null;

            String nodeType = curNode.getString("type");

            if(nodeType.equals("condition")){
                continue;
            }

            if(i < (jsonArray.size() - 1)){
                nextNode = (JSONObject) jsonArray.get(i + 1);
            }

            // 遍历节点处理器，进行相关处理
            for (ProcessNodeResolver processNodeResolver : resolverList) {
                if(processNodeResolver.support(nodeType)){
                    processNodeResolver.addFlowNodeToActiviti(process, curNode, nextNode);
                }
            }

        }
    }

    @Override
    public void deleteProcessDefinition(ApproveDefinition approveDefinition) {

        // 获取在activiti中的流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(ActivitiUtils.PROCESS_PREFIX + approveDefinition.getId())
                .singleResult();

        if(processDefinition!=null){
            // 删除流程定义信息
            repositoryService.deleteDeployment(processDefinition.getDeploymentId());
        }
    }
}
